package com.axend.lib_base.help;

import android.util.Log;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class TempProcess {
    private int dataCount_temp = 0;
    private float previousAverage = 0.0f;
    private float trimmedAverage = 0.0f;
    private float ema = 0.0f; // 初始 EMA 值
    private float alpha = 0.2f; // 平滑因子

    private int dataSize = 10;
    private List<Float> tempListSort;
    List<Float> subtempList = new ArrayList<>();
    private float threshold = 0.5f;

    private float dataPrev2;  // 前两个数据
    private float dataPrev1; // 前一个数据
    private float dataCurr; // 当前数据

    public float addTempData(float bodyMaxTemp, List<Float> tempList, int dataSize, Boolean isClearList) {
        return processAndCalculateAverage(bodyMaxTemp, tempList, dataSize, isClearList);
    }

    private float processAndCalculateAverage(float bodyMaxTemp, List<Float> tempList, int dataSize, Boolean isClearList) {
        if (isClearList) {
            tempList.clear();
            dataCount_temp = 0;
        }
        // 将新数据加入 tempList
        tempList.add(bodyMaxTemp);
        dataCount_temp += 1;

        // 如果数据超过dataSize个，移除最旧的数据
//        if (tempList.size() > dataSize) {
//            tempList.remove(0);
//            // 删除旧数据后重新赋值给新的列表
//            tempListSort = new ArrayList<>(tempList); // 用于输出过滤后的体表最高温
//            dataCount_temp -= 1;
//        }
        // 只有数量满足要求时才计算数据
        if (dataCount_temp == dataSize && tempList.size() == dataSize) {
            tempListSort = new ArrayList<>(tempList); // 用于输出过滤后的体表最高温,排序用，不改变tempList
//            if (methodFlag.get(0)) {
////                // 处理新加入的值
////                subtempList.add(tempList.get(dataCount_temp - 2));
////                subtempList.add(tempList.get(dataCount_temp - 1));
////                // 利用相邻两个数据比较后输出
////                trimmedAverage = filterTwoBodyMaxTemp(subtempList, threshold);
////                tempList.set(dataCount_temp - 1, trimmedAverage); // 更新列表
////                subtempList.remove(dataCount_temp - 2); // 移除旧数据
////                // 更新拷贝列表
////                tempListSort = new ArrayList<>(tempList); // 用于输出过滤后的体表最高温,排序用，不改变tempList
//                // 取中位数:直接取中位数
//                trimmedAverage = calculateMedian(tempListSort);
//            } else if (methodFlag.get(1)) {
//                // 去掉10%的数据
//                trimmedAverage = calculateTrimmedMean(tempListSort);
//            } else if (methodFlag.get(2)) {
//                // 计算去掉最大值和最小值后的平均值
//                trimmedAverage = calculateTrimmedAverage(tempListSort);
//            } else if (methodFlag.get(3)) {
                /**需要融合到app中：优先使用该方法*/
                // EMA：移动平均
                List<Float> emaValues = new ArrayList<>();
                emaValues = calculateEMA(tempListSort, alpha);
//                // 取中位数
                trimmedAverage = calculateMedian(emaValues);
                //
//                trimmedAverage = calculateTrimmedAllMaxMinMean(emaValues);
//            } else if (methodFlag.get(6)) {
//                // 去除所有的最大值和最小值后的平均值：如果去除后数据为空，则取最大和最小平均值
//                trimmedAverage = calculateTrimmedAllMaxMinMean(tempListSort);
//            }

            tempList.remove(0);
            dataCount_temp -= 1;

//        } else if (dataCount_temp > 1 && dataCount_temp < dataSize) {
//            tempListSort = new ArrayList<>(tempList); // 用于输出过滤后的体表最高温，排序用，不改变tempList
//            if (methodFlag.get(0)) {
////                    subtempList.add(tempList.get(dataCount_temp - 2));
////                    subtempList.add(tempList.get(dataCount_temp - 1));
////                    // 利用相邻两个数据比较后输出
////                    trimmedAverage = filterTwoBodyMaxTemp(subtempList, threshold);
////                    tempList.set(dataCount_temp - 1, trimmedAverage); // 更新列表
////                    subtempList.remove(dataCount_temp - 2); // 移除旧数据
//                // 更新拷贝列表
////                tempListSort = new ArrayList<>(tempList); // 用于输出过滤后的体表最高温,排序用，不改变tempList
//                // 取中位数
//                trimmedAverage = calculateMedian(tempListSort);
//            } else if (methodFlag.get(3)) {
//                // EMA
//                List<Float> emaValues = new ArrayList<>();
//                emaValues = calculateEMA(tempListSort, alpha);
//                // 取中位数
//                trimmedAverage = calculateMedian(emaValues);
//            } else {
//                // 数量小于3个时，直接计算平均值:方法①去掉10%的数据②计算去掉最大值和最小值后的平均值
//                trimmedAverage = calculateSimpleAverage(tempListSort);
//            }


        } else if (dataCount_temp > 1 && dataCount_temp < dataSize) {
            tempListSort = new ArrayList<>(tempList); // 用于输出过滤后的体表最高温
//            if (methodFlag.get(0)) {
//                // 取中位数
//                trimmedAverage = calculateMedian(tempListSort);
//
////                subtempList.add(tempList.get(dataCount_temp - 1));
////                if (subtempList.size() == 3) {
////                    // 利用相邻三个数据比较后输出
////                    trimmedAverage = filterThreeBodyMaxTemp(subtempList, threshold);
////                    subtempList.remove(0);
////                }
//
//            } else if (methodFlag.get(1)) {
//                // 去掉10%的数据
//                trimmedAverage = calculateTrimmedMean(tempListSort);
//            } else if (methodFlag.get(2)) {
//                // 计算去掉最大值和最小值后的平均值
//                trimmedAverage = calculateTrimmedAverage(tempListSort);
//            } else if (methodFlag.get(3)) {
                /**需要融合到app中：优先使用该方法*/
                // EMA
                List<Float> emaValues = new ArrayList<>();
                emaValues = calculateEMA(tempListSort, alpha);
                // 取中位数
                trimmedAverage = calculateMedian(emaValues);
//            } else if (methodFlag.get(6)) {
//                // 去除所有的最大值和最小值后的平均值：如果去除后数据为空，则取最大和最小平均值
//                trimmedAverage = calculateTrimmedAllMaxMinMean(tempListSort);
//            }
        }
        Log.d("Processed Data", "Trimmed Average temperature: " + trimmedAverage);
        previousAverage = trimmedAverage;
        // 注释掉：不加入上一次的计算结果
//        tempList.add(previousAverage); // 加入上一次计算的结果
//        dataCount_temp += 1;
//        //如果数据超过10个，移除最旧的数据
//        if (tempList.size() > dataSize) {
//            tempList.remove(0);
//            dataCount_temp -= 1;
//        }
        return previousAverage;
    }

    private float calculateSimpleAverage(List<Float> tempList) {
        float sum = 0;
        for (float temp : tempList) {
            sum += temp;
        }
        return sum / tempList.size();
    }

    private float calculateTrimmedAverage(List<Float> tempList) {
        if (tempList.size() < 3) {
            throw new IllegalArgumentException("List must contain at least three elements.");
        }

        float sum = 0;
        float max = Float.NEGATIVE_INFINITY;
        float min = Float.POSITIVE_INFINITY;

        // 找到最大值和最小值，并累加总和
        for (float temp : tempList) {
            sum += temp;
            if (temp > max) {
                max = temp;
            }
            if (temp < min) {
                min = temp;
            }
        }

        // 去掉最大值和最小值后的总和
        sum -= (max + min);

        // 计算平均值
        return sum / (tempList.size() - 2);
    }

    private float calculateTrimmedMean(List<Float> list) {
        if (list.size() < 3) {
            throw new IllegalArgumentException("List must contain at least three elements.");
        }

        Collections.sort(list);

        int trimSize = (int) Math.ceil(list.size() * 0.1); // 去掉10%的数据
        List<Float> trimmedList = list.subList(trimSize, list.size() - trimSize);

        float sum = 0;
        for (float temp : trimmedList) {
            sum += temp;
        }

        return sum / trimmedList.size();
    }

    private float calculateTrimmedAllMaxMinMean(List<Float> list) {
//        if (list.size() < 3) {
//            throw new IllegalArgumentException("List must contain at least three elements.");
//        }

        // 步骤1: 对数据进行排序
        Collections.sort(list);

        // 步骤2: 获取最大值和最小值
        float max_value = list.get(list.size() - 1);
        float min_value = list.get(0);

        // 步骤3: 去除最大值和最小值相同的所有数据
        List<Float> trimmedList = new ArrayList<>();
        for (float value : list) {
            if (value != max_value && value != min_value) {
                trimmedList.add(value);
            }
        }

        // 步骤4: 计算剩余数据的平均值
        if (trimmedList.isEmpty()) {
            return (max_value + min_value) / 2;
        }
        float sum = 0;
        for (float temp : trimmedList) {
            sum += temp;
        }

        return sum / trimmedList.size();
    }

    /**
     * 计算列表的中位数
     *
     * @param numbers 包含数值的列表
     * @return 中位数
     */
    public static float calculateMedian(List<Float> numbers) {
        // 对列表进行排序
        Collections.sort(numbers);

        int size = numbers.size();
        if (size % 2 == 0) { // 偶数个元素
            return (numbers.get(size / 2 - 1) + numbers.get(size / 2)) / 2;
        } else { // 奇数个元素
            return numbers.get(size / 2);
        }
    }

    /**
     * 计算带有中位数修剪的指数移动平均值
     *
     * @param tempList 临时数据列表
     * @param ema      当前的 EMA 值
     * @param alpha    平滑因子
     * @return 更新后的 EMA 值
     */
    public static float calculateTrimmedEMA(List<Float> tempList, float ema, float alpha, float trimmedAverage) {
//        // 计算中位数
        trimmedAverage = calculateMedian(tempList);

        // 更新 EMA
        if (ema == 0.0f) {
            ema = trimmedAverage; // 第一次使用中位数作为初始值
        } else {
            ema = alpha * trimmedAverage + (1 - alpha) * ema;
        }

        return ema;
    }

    /**
     * 计算指数移动平均值
     *
     * @param data  数据点列表
     * @param alpha 平滑因子
     * @return EMA 值列表
     */
    public static List<Float> calculateEMA(List<Float> data, float alpha) {
        List<Float> emaValues = new ArrayList<>();

        if (data.isEmpty()) {
            throw new IllegalArgumentException("Data list cannot be empty.");
        }

        // 初始化 EMA 值
        float ema = data.get(0);
        emaValues.add(ema);

        // 计算 EMA 值
        for (int i = 1; i < data.size(); i++) {
            float x = data.get(i);
            ema = alpha * x + (1 - alpha) * ema;
            emaValues.add(ema);
        }

        return emaValues;
    }

    /*利用相邻最高温差值与接受阈值对比过滤体表最高温后输出*/
    public float filterBodyMaxTemp(float dataPrev1, float dataCurr, float thresh) {
        float diff;

        // 计算当前数据与前一个数据的差值
        diff = dataCurr - dataPrev1;
        int k = 2;

        // 如果差值超过阈值，则返回前一个数据；否则返回当前数据
        if (Math.abs(diff) > thresh) {
            return dataPrev1 + diff / k;
        } else {
            return dataCurr;
        }
    }

    public float filterTwoBodyMaxTemp(List<Float> tempList, float thresh) {
        float diff;

        dataPrev1 = tempList.get(0);
        dataCurr = tempList.get(1);


        // 计算当前数据与前一个数据的差值
        diff = dataCurr - dataPrev1;
//        float k0 = 0.5f;
//        int k1 = 2;
//        int k2 = 3;

        // 如果差值超过阈值，则返回前一个数据；否则返回当前数据
        if (Math.abs(diff) > thresh) {
//            return dataPrev1 + diff / 10;
            if (diff > 0) {
                return dataPrev1 + thresh;
            } else {
                return dataPrev1 - thresh;
            }
        } else {
            return dataCurr;
        }
    }

    // 相邻数据滤波
    public float filterThreeBodyMaxTemp(List<Float> tempList, float thresh) {
        float forwardDiff, backwardDiff;
        float x1, x2, y0, y1, y2, x, y;


        // 累积三个数据一组输出一个当前温度
//           初始化当前数据和前两个数据
        dataPrev2 = tempList.get(0);
        dataPrev1 = tempList.get(1);
        dataCurr = tempList.get(2);

        backwardDiff = dataPrev1 - dataPrev2;
        forwardDiff = dataPrev1 - dataCurr;

        x1 = 0;
        x2 = 2;
        y0 = dataPrev2;
        y1 = dataPrev1;
        y2 = dataCurr;
        x = 1;

        if (Math.abs(forwardDiff) > thresh && (Math.abs(backwardDiff) < thresh)) {
            y = dataPrev1;
        } else if (Math.abs(backwardDiff) > thresh && Math.abs(forwardDiff) < thresh) {
            y = dataPrev1;
        } else if (Math.abs(backwardDiff) > thresh && Math.abs(forwardDiff) > thresh) {
            if (Math.abs(backwardDiff) < 2 * thresh && Math.abs(forwardDiff) < 2 * thresh) {
                y = y1 + (((x - x1) * forwardDiff) / (x2 - x1));
            } else {
                if (forwardDiff > 0) {
                    y = y1 + thresh / 2;
                } else {
                    y = y1 - thresh / 2;
                }
            }
        } else {
            y = dataPrev1;
        }
        return y;
    }

    public float filterBodyMaxTemp(List<Float> pDataIn, float thresh) {
        float forwardDiff, backwardDiff;
        float x1, x2, y1, y2, x, y;


        backwardDiff = pDataIn.get(1) - pDataIn.get(0);
        forwardDiff = pDataIn.get(1) - pDataIn.get(2);

        x1 = 0;
        x2 = 2;
        y1 = pDataIn.get(1);
        y2 = pDataIn.get(2);
        x = 1;

        if (((forwardDiff > thresh) && (backwardDiff > thresh)) || ((forwardDiff < -thresh) && (backwardDiff < -thresh)))
            y = y1 + (((x - x1) * (y2 - y1)) / (x2 - x1));
        else
            y = pDataIn.get(1);

        return y;

    }

    public float filterBodyMaxTemp(float dataPrev2, float dataPrev1, float dataCurr, float thresh) {
        float forwardDiff, backwardDiff;
        float x1, x2, y1, y2, x, y;
        float[] pDataIn = new float[3];

        pDataIn[0] = dataPrev2;
        pDataIn[1] = dataPrev1;
        pDataIn[2] = dataCurr;

        backwardDiff = pDataIn[1] - pDataIn[0];
        forwardDiff = pDataIn[1] - pDataIn[2];

        x1 = 0;
        x2 = 2;
        y1 = pDataIn[0];
        y2 = pDataIn[2];
        x = 1;

        if ((Math.abs(forwardDiff) > thresh) && (Math.abs(backwardDiff) > thresh))
            y = y1 + (((x - x1) * (y2 - y1)) / (x2 - x1));
        else
            y = pDataIn[1];

        return y;

    }

}
